﻿using System;
using System.Threading;
using System.Xml;

namespace wojilu
{
    public class YBBCache
    {
        private static ICacheStrategy cs = new DefaultCacheStrategy();
        private static volatile YBBCache instance = null;
        private static object lockHelper = new object();
        private static XmlDocument rootXml = new XmlDocument();
        private static XmlElement objectXmlMap = rootXml.CreateElement("Cache");

        private YBBCache()
        {
            rootXml.AppendChild(objectXmlMap);
        }

        public virtual void AddObject(string string_0, object object_0)
        {
            lock (lockHelper)
            {
                if (cs.TimeOut > 0)
                {
                    string str = this.method_1(string_0);
                    int length = str.LastIndexOf("/");
                    string xpath = str.Substring(0, length);
                    string name = str.Substring(length + 1);
                    XmlNode node = objectXmlMap.SelectSingleNode(xpath);
                    string str4 = "";
                    XmlNode oldChild = objectXmlMap.SelectSingleNode(this.method_1(string_0));
                    if (oldChild != null)
                    {
                        str4 = oldChild.Attributes["objectId"].Value;
                    }
                    if (str4 == "")
                    {
                        node = this.method_0(xpath);
                        str4 = Guid.NewGuid().ToString();
                        XmlElement newChild = objectXmlMap.OwnerDocument.CreateElement(name);
                        XmlAttribute attribute = objectXmlMap.OwnerDocument.CreateAttribute("objectId");
                        attribute.Value = str4;
                        newChild.Attributes.Append(attribute);
                        node.AppendChild(newChild);
                    }
                    else
                    {
                        XmlElement element2 = objectXmlMap.OwnerDocument.CreateElement(name);
                        XmlAttribute attribute2 = objectXmlMap.OwnerDocument.CreateAttribute("objectId");
                        attribute2.Value = str4;
                        element2.Attributes.Append(attribute2);
                        node.ReplaceChild(element2, oldChild);
                    }
                    cs.AddObject(str4, object_0);
                }
            }
        }

        public virtual void AddObject(string string_0, object object_0, int int_0)
        {
            lock (lockHelper)
            {
                if (cs.TimeOut > 0)
                {
                    string str = this.method_1(string_0);
                    int length = str.LastIndexOf("/");
                    string xpath = str.Substring(0, length);
                    string name = str.Substring(length + 1);
                    XmlNode node = objectXmlMap.SelectSingleNode(xpath);
                    string str4 = "";
                    XmlNode oldChild = objectXmlMap.SelectSingleNode(this.method_1(string_0));
                    if (oldChild != null)
                    {
                        str4 = oldChild.Attributes["objectId"].Value;
                    }
                    if (str4 == "")
                    {
                        node = this.method_0(xpath);
                        str4 = Guid.NewGuid().ToString();
                        XmlElement newChild = objectXmlMap.OwnerDocument.CreateElement(name);
                        XmlAttribute attribute = objectXmlMap.OwnerDocument.CreateAttribute("objectId");
                        attribute.Value = str4;
                        newChild.Attributes.Append(attribute);
                        node.AppendChild(newChild);
                    }
                    else
                    {
                        XmlElement element2 = objectXmlMap.OwnerDocument.CreateElement(name);
                        XmlAttribute attribute2 = objectXmlMap.OwnerDocument.CreateAttribute("objectId");
                        attribute2.Value = str4;
                        element2.Attributes.Append(attribute2);
                        node.ReplaceChild(element2, oldChild);
                    }
                    cs.AddObject(str4, object_0, int_0);
                }
            }
        }

        public virtual void AddObject(string string_0, object object_0, string[] string_1)
        {
            string_0 = string_0.Replace(" ", "_SPACE_");
            lock (lockHelper)
            {
                if (cs.TimeOut > 0)
                {
                    string str = this.method_1(string_0);
                    int length = str.LastIndexOf("/");
                    string xpath = str.Substring(0, length);
                    string name = str.Substring(length + 1);
                    XmlNode node = objectXmlMap.SelectSingleNode(xpath);
                    string str4 = "";
                    XmlNode oldChild = objectXmlMap.SelectSingleNode(this.method_1(string_0));
                    if (oldChild != null)
                    {
                        str4 = oldChild.Attributes["objectId"].Value;
                    }
                    if (str4 == "")
                    {
                        node = this.method_0(xpath);
                        str4 = Guid.NewGuid().ToString();
                        XmlElement newChild = objectXmlMap.OwnerDocument.CreateElement(name);
                        XmlAttribute attribute = objectXmlMap.OwnerDocument.CreateAttribute("objectId");
                        attribute.Value = str4;
                        newChild.Attributes.Append(attribute);
                        node.AppendChild(newChild);
                    }
                    else
                    {
                        XmlElement element2 = objectXmlMap.OwnerDocument.CreateElement(name);
                        XmlAttribute attribute2 = objectXmlMap.OwnerDocument.CreateAttribute("objectId");
                        attribute2.Value = str4;
                        element2.Attributes.Append(attribute2);
                        node.ReplaceChild(element2, oldChild);
                    }
                    cs.AddObjectWithFileChange(str4, object_0, string_1);
                }
            }
        }

        /// <summary>
        /// 清除缓存
        /// </summary>
        public void FlushAll()
        {
            cs.FlushAll();
        }

        /// <summary>
        /// 获取当前实体
        /// </summary>
        /// <returns></returns>
        public static YBBCache GetCacheService()
        {
            if (instance == null)
            {
                lock (lockHelper)
                {
                    if (instance == null)
                    {
                        instance = new YBBCache();
                    }
                }
            }
            return instance;
        }

        public void LoadCacheStrategy(ICacheStrategy icacheStrategy_0)
        {
            lock (lockHelper)
            {
                cs = icacheStrategy_0;
            }
        }

        public void LoadDefaultCacheStrategy()
        {
            lock (lockHelper)
            {
                cs = new DefaultCacheStrategy();
            }
        }

        private XmlNode method_0(string string_0)
        {
            lock (lockHelper)
            {
                string[] strArray = string_0.Split(new char[] { '/' });
                string xpath = "";
                XmlNode objectXmlMap = YBBCache.objectXmlMap;
                for (int i = 1; i < strArray.Length; i++)
                {
                    if (YBBCache.objectXmlMap.SelectSingleNode(xpath + "/" + strArray[i]) == null)
                    {
                        XmlElement newChild = YBBCache.objectXmlMap.OwnerDocument.CreateElement(strArray[i]);
                        objectXmlMap.AppendChild(newChild);
                    }
                    xpath = xpath + "/" + strArray[i];
                    objectXmlMap = YBBCache.objectXmlMap.SelectSingleNode(xpath);
                }
                return objectXmlMap;
            }
        }

        private string method_1(string string_0)
        {
            lock (lockHelper)
            {
                string[] strArray = string_0.Split(new char[] { '/' });
                string_0 = "/Cache";
                foreach (string str in strArray)
                {
                    if (str != "")
                    {
                        string_0 = string_0 + "/" + str;
                    }
                }
                return string_0;
            }
        }

        public virtual void RemoveObject(string string_0)
        {
            object obj2;
            Monitor.Enter(obj2 = lockHelper);
            try
            {
                XmlNode oldChild = objectXmlMap.SelectSingleNode(this.method_1(string_0));
                if (oldChild.HasChildNodes)
                {
                    XmlNodeList list = oldChild.SelectNodes("*[@objectId]");
                    string str = "";
                    foreach (XmlNode node2 in list)
                    {
                        str = node2.Attributes["objectId"].Value;
                        node2.ParentNode.RemoveChild(node2);
                        cs.RemoveObject(str);
                    }
                }
                else
                {
                    string str2 = oldChild.Attributes["objectId"].Value;
                    oldChild.ParentNode.RemoveChild(oldChild);
                    cs.RemoveObject(str2);
                }
            }
            catch
            {
            }
            finally
            {
                Monitor.Exit(obj2);
            }
        }

        public virtual object RetrieveObject(string string_0)
        {
            try
            {
                XmlNode node = objectXmlMap.SelectSingleNode(this.method_1(string_0));
                if (node != null)
                {
                    return cs.RetrieveObject(node.Attributes["objectId"].Value);
                }
                return null;
            }
            catch
            {
                return null;
            }
        }

    }
}